<template>
  <div v-if="visible" class="judge-popup-overlay" @click="handleOverlayClick">
    <div class="judge-popup" @click.stop>
      <!-- 弹窗标题栏 -->
      <div class="popup-header">
        <h3 class="popup-title">gocJudge测评</h3>
        <button class="close-btn" @click="closePopup">×</button>
      </div>

      <!-- 主要内容区域 -->
      <div class="popup-content">
        <!-- 左侧：标准程序结果 -->
        <div class="left-section">
          <div class="section-header">
            <h4 class="section-title">标准程序结果</h4>
            <button class="draw-coords-btn" @click="drawCoordinates('standard')">
              <span class="btn-icon">▲</span>
              {{ showStandardCoordinates ? '隐藏坐标' : '画坐标' }}
            </button>
          </div>
          <div class="canvas-container">
            <div class="canvas-wrap">
              <canvas 
                ref="standardAxisCanvas" 
                class="axis-canvas"
                width="900" 
                height="900"
              ></canvas>
            <canvas 
              ref="standardCanvas" 
              class="judge-canvas"
                width="900" 
                height="900"
            ></canvas>
            </div>
          </div>
          <div class="io-fields">
            <div class="io-field">
              <label>cinWin</label>
              <input type="text" v-model="standardInput" readonly />
            </div>
            <div class="io-field">
              <label>coutWin</label>
              <input type="text" v-model="standardOutput" readonly />
            </div>
          </div>
        </div>

        <!-- 中间：用户程序结果 -->
        <div class="middle-section">
          <div class="section-header">
            <h4 class="section-title">您的程序结果</h4>
            <button class="draw-coords-btn" @click="drawCoordinates('user')">
              <span class="btn-icon">▲</span>
              {{ showUserCoordinates ? '隐藏坐标' : '画坐标' }}
            </button>
          </div>
          <div class="canvas-container">
            <div class="canvas-wrap">
              <canvas 
                ref="userAxisCanvas" 
                class="axis-canvas"
                width="900" 
                height="900"
              ></canvas>
            <canvas 
              ref="userCanvas" 
              class="judge-canvas"
                width="900" 
                height="900"
            ></canvas>
            </div>
          </div>
          <div class="io-fields">
            <div class="io-field">
              <label>cinWin</label>
              <input type="text" v-model="userInput" readonly />
            </div>
            <div class="io-field">
              <label>coutWin</label>
              <input type="text" v-model="userOutput" readonly />
            </div>
          </div>
        </div>

        <!-- 右侧：测试完成信息 -->
        <div class="right-section">
          <div class="test-complete-header">
            <h4 class="test-complete-title">测试完成!</h4>
          </div>
          
          <!-- 图片比对控制区域 -->
          <div class="comparison-controls">
            <!-- 自动图片对比提示 -->
            <div class="auto-compare-notice">
              <div class="notice-icon">🔄</div>
              <div class="notice-text">判题完成</div>
            </div>
            <button 
              class="download-btn" 
              @click="downloadImages"
            >
              下载图片到本地
            </button>
            
          </div>

          <!-- 比对结果 -->
          <div v-if="comparisonResult" class="comparison-result">
            <h5>比对结果</h5>
            <div class="result-score">得分: {{ comparisonResult.score }}</div>
            <div class="result-details">{{ comparisonResult.feedback }}</div>
            
            <!-- 有输入型题目的详细结果 -->
            <div v-if="hasInputType && testCaseResults.length > 0" class="test-case-results">
              <h6>测试用例详细结果</h6>
              <div class="test-case-list">
                <div 
                  v-for="(result, index) in testCaseResults" 
                  :key="index"
                  class="test-case-item"
                  :class="{ 'success': result.success, 'error': !result.success }"
                >
                  <div class="test-case-header">
                    <span class="test-case-number">测试用例 {{ index + 1 }}</span>
                    <span class="test-case-score">{{ result.score }}分</span>
                    <span class="test-case-status">{{ result.success ? '✓' : '✗' }}</span>
                  </div>
                  <div class="test-case-input">
                    <strong>输入:</strong> {{ getTestCaseInput(index) }}
                  </div>
                  <div class="test-case-feedback">{{ result.feedback }}</div>
                  <div v-if="result.error" class="test-case-error">错误: {{ result.error }}</div>
                </div>
              </div>
            </div>
          </div>

        </div>
      </div>
    </div>
  </div>
</template>

<script>
import { ref, computed, onMounted, nextTick, watch } from 'vue'
import logger from '../utils/logger.js'

export default {
  name: 'JudgeComparisonPopup',
  props: {
    visible: {
      type: Boolean,
      default: false
    },
    userCode: {
      type: String,
      default: ''
    },
    answerCode: {
      type: String,
      default: ''
    },
    comparisonResults: {
      type: Array,
      default: () => []
    },
    testCases: {
      type: Array,
      default: () => []
    }
  },
  emits: ['close'],
  setup(props, { emit }) {
    // 调试信息：检查接收到的props
    logger.log('🔍 [JudgeComparisonPopup] 组件初始化，接收到的props:', {
      visible: props.visible,
      userCode: props.userCode,
      answerCode: props.answerCode,
      testCases: props.testCases,
      testCasesLength: props.testCases ? props.testCases.length : 0
    })
    
    // 响应式数据
    const standardCanvas = ref(null)
    const userCanvas = ref(null)
    const standardAxisCanvas = ref(null)
    const userAxisCanvas = ref(null)
    const standardInput = ref('')
    const standardOutput = ref('')
    const userInput = ref('')
    const userOutput = ref('')
    const isExecuting = ref(false)
    
    // 图片比对相关状态
    const isComparing = ref(false)
    const comparisonResult = ref(null)
    
    // 坐标显示状态
    const showStandardCoordinates = ref(false)
    const showUserCoordinates = ref(false)
    
    // 有输入型题目相关状态
    const currentTestCaseIndex = ref(0)
    const testCaseResults = ref([])
    const isRunningAllTests = ref(false)
    const overallScore = ref(0)
    const hasInputType = computed(() => {
      if (!props.testCases || !Array.isArray(props.testCases) || props.testCases.length === 0) {
        return false
      }
      return props.testCases.some(tc => tc && tc.input && tc.input !== '无输入')
    })

    // 安全的测试用例访问
    const safeTestCases = computed(() => {
      return props.testCases && Array.isArray(props.testCases) ? props.testCases : []
    })

    const safeTestCasesLength = computed(() => {
      return safeTestCases.value.length
    })

    const getTestCaseInput = (index) => {
      const testCase = safeTestCases.value[index]
      return testCase && testCase.input ? testCase.input : '无输入'
    }

    // 计算属性
    const canCompare = computed(() => {
      return standardCanvas.value && userCanvas.value && !isExecuting.value
    })

    // 关闭弹窗
    const closePopup = () => {
      emit('close')
    }

    // 点击遮罩层关闭弹窗
    const handleOverlayClick = (event) => {
      if (event.target === event.currentTarget) {
        closePopup()
      }
    }

    // 画坐标功能 - 切换坐标显示状态
    const drawCoordinates = (type) => {
      const axisCanvas = type === 'standard' ? standardAxisCanvas.value : userAxisCanvas.value
      
      if (!axisCanvas) {
        logger.error(`${type}坐标轴画布未找到`)
        return
      }

      // 切换坐标显示状态
      if (type === 'standard') {
        showStandardCoordinates.value = !showStandardCoordinates.value
      } else {
        showUserCoordinates.value = !showUserCoordinates.value
      }

      // 根据状态显示或隐藏坐标轴画布
      const showCoords = type === 'standard' ? showStandardCoordinates.value : showUserCoordinates.value
      axisCanvas.style.display = showCoords ? 'block' : 'none'
      
      logger.log(`${type}画布坐标显示状态已切换为: ${showCoords}`)
      logger.log(`${type}坐标轴画布display样式: ${axisCanvas.style.display}`)
      logger.log(`${type}坐标轴画布尺寸: ${axisCanvas.width}x${axisCanvas.height}`)
      
      // 如果显示坐标，绘制坐标网格
      if (showCoords) {
        drawCoordinateGrid(axisCanvas, 900, 900)
        logger.log(`${type}坐标网格已绘制`)
      }
    }

    // 绘制坐标网格（在坐标轴画布上绘制）
    const drawCoordinateGrid = (canvas, width, height) => {
      const ctx = canvas.getContext('2d')
      if (!ctx) {
        logger.error('无法获取坐标轴画布的2D上下文')
        return
      }
      
      logger.log(`开始绘制坐标网格，画布尺寸: ${width}x${height}`)

      // 清除画布
      ctx.clearRect(0, 0, width, height)
      
      // 保存当前状态
      ctx.save()
      
      // 设置坐标轴样式 - 红色虚线
      ctx.strokeStyle = '#ff0000' // 红色
      ctx.lineWidth = 1
      ctx.setLineDash([5, 5]) // 虚线
      ctx.font = '14px Arial'
      ctx.fillStyle = '#000000' // 黑色文字

      // 计算中心点（900x900画布的中心）
      const centerX = width / 2
      const centerY = height / 2
      
      logger.log(`中心点坐标: (${centerX}, ${centerY})`)

      // 画坐标轴 - 只在整百位置绘制网格线
      // 垂直线 - 从-400到400，每100一条线
      for (let x = -400; x <= 400; x += 100) {
        const pixelX = centerX + x
        if (pixelX >= 0 && pixelX <= width) {
        ctx.beginPath()
          ctx.moveTo(pixelX, 0)
          ctx.lineTo(pixelX, height)
        ctx.stroke()
          
          // 添加X轴数值标注
          ctx.textAlign = 'center'
          ctx.fillText(x.toString(), pixelX, 20)
        }
      }

      // 水平线 - 从-400到400，每100一条线
      for (let y = -400; y <= 400; y += 100) {
        const pixelY = centerY - y // Y轴向上为正
        if (pixelY >= 0 && pixelY <= height) {
        ctx.beginPath()
          ctx.moveTo(0, pixelY)
          ctx.lineTo(width, pixelY)
        ctx.stroke()
          
          // 添加Y轴数值标注
          ctx.textAlign = 'right'
          ctx.fillText(y.toString(), 20, pixelY + 4)
        }
      }

      // 绘制中心点标记
      ctx.setLineDash([]) // 实线
      ctx.beginPath()
      ctx.arc(centerX, centerY, 3, 0, 2 * Math.PI)
      ctx.fillStyle = 'red'
      ctx.fill()

      // 恢复状态
      ctx.restore()
      
      logger.log('坐标网格绘制完成')
    }

    // 将Canvas转换为Base64
    const canvasToBase64 = (canvas) => {
      if (!canvas) {
        logger.warn('canvasToBase64: 画布为空')
        return null
      }
      
      try {
        // 检查画布尺寸
        logger.log('canvasToBase64: 画布尺寸', canvas.width, 'x', canvas.height)
        
        // 检查画布内容
        const ctx = canvas.getContext('2d')
        const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height)
        
        // 检查是否有非透明像素
        let hasContent = false
        let nonTransparentPixels = 0
        
        for (let i = 3; i < imageData.data.length; i += 4) {
          if (imageData.data[i] > 0) { // alpha > 0
            hasContent = true
            nonTransparentPixels++
          }
        }
        
        logger.log('canvasToBase64: 画布内容检查', {
          hasContent,
          nonTransparentPixels,
          totalPixels: imageData.data.length / 4
        })
        
        if (!hasContent) {
          logger.warn('canvasToBase64: 画布内容为空，没有非透明像素')
        }
        
        // 生成Base64
        const base64 = canvas.toDataURL('image/png')
        logger.log('canvasToBase64: 生成的Base64长度', base64.length)
        
        // 验证Base64格式
        if (!base64.startsWith('data:image/png;base64,')) {
          logger.error('canvasToBase64: Base64格式错误', base64.substring(0, 50))
          return null
        }
        
        return base64
        
      } catch (error) {
        logger.error('canvasToBase64: 转换失败', error)
        return null
      }
    }

    // 将Base64转换为Blob
    const base64ToBlob = (base64) => {
      if (!base64) {
        logger.warn('base64ToBlob: Base64数据为空')
        return null
      }
      
      try {
        const arr = base64.split(',')
        if (arr.length !== 2) {
          logger.error('base64ToBlob: Base64格式错误，缺少逗号分隔符')
          return null
        }
        
        const mime = arr[0].match(/:(.*?);/)[1]
        if (!mime) {
          logger.error('base64ToBlob: 无法解析MIME类型')
          return null
        }
        
        const bstr = atob(arr[1])
        let n = bstr.length
        const u8arr = new Uint8Array(n)
        while (n--) {
          u8arr[n] = bstr.charCodeAt(n)
        }
        
        const blob = new Blob([u8arr], { type: mime })
        logger.log('base64ToBlob: 创建Blob成功', {
          mime,
          size: blob.size,
          type: blob.type
        })
        
        return blob
        
      } catch (error) {
        logger.error('base64ToBlob: 转换失败', error)
        return null
      }
    }

    // 自动图片对比方法
    const autoCompareImages = async () => {
      if (!canCompare.value) {
        logger.warn('无法进行自动图片比对：画布未准备好')
        return
      }

      try {
        isComparing.value = true
        comparisonResult.value = null
        logger.log('🚀 开始自动图片比对...')

        // 检查是否为有输入型题目
        if (hasInputType.value) {
          logger.log('🔍 检测到有输入型题目，自动执行所有测试用例')
          await compareAllTestCases()
          return
        }

        // 无输入型题目的单次比对
        logger.log('🔍 无输入型题目，执行单次图片比对')
        
        // 等待画布渲染完成
        await new Promise(resolve => setTimeout(resolve, 1000))

        // 获取两张图片的Base64数据
        const standardBase64 = canvasToBase64(standardCanvas.value)
        const userBase64 = canvasToBase64(userCanvas.value)

        if (!standardBase64 || !userBase64) {
          throw new Error('无法获取画布图片数据')
        }

        // 转换为Blob
        const standardBlob = base64ToBlob(standardBase64)
        const userBlob = base64ToBlob(userBase64)

        // 创建FormData
        const formData = new FormData()
        formData.append('image1', standardBlob, 'standard.png')
        formData.append('image2', userBlob, 'user.png')
        formData.append('strict', 'true')

        // 获取用户 token
        const token = localStorage.getItem('token')
        const headers = {}
        
        if (token) {
          headers['Authorization'] = token
        }
        
        const response = await fetch('/api/goc/images/compare', {
          method: 'POST',
          headers: headers,
          body: formData
        })
        
        if (!response.ok) {
          throw new Error(`HTTP错误: ${response.status}`)
        }

        const result = await response.json()
        logger.log('自动图片比对结果:', result)

        // 处理返回结果
        if (result.code === 0) {
          comparisonResult.value = {
            score: result.data?.score || 0,
            similar: result.data?.similar,
            feedback: result.data?.feedback || result.message || '比对完成'
          }
          
          // 🔥 触发判题完成事件，传递得分给父组件
          logger.log('🚨🚨🚨 [JudgeComparisonPopup] ========== autoCompareImages 触发 judge-complete 事件！ ==========')
          logger.log('✅ [JudgeComparisonPopup] 自动图片比对完成，触发 judge-complete 事件')
          logger.log('📊 [JudgeComparisonPopup] 得分:', result.data?.score)
          logger.log('📊 [JudgeComparisonPopup] 相似度:', result.data?.similar)
          
          const judgeCompleteData = {
            score: result.data?.score || 0,
            similar: result.data?.similar,
            feedback: result.data?.feedback || result.message || '比对完成'
          }
          logger.log('📤 [JudgeComparisonPopup] 发送的数据:', judgeCompleteData)
          
          emit('judge-complete', judgeCompleteData)
          
          logger.log('✅ [JudgeComparisonPopup] judge-complete 事件已触发')
        } else {
          const errorMsg = result.message || result.data || '比对失败'
          comparisonResult.value = {
            score: 0,
            feedback: `比对失败: ${errorMsg}。建议尝试关闭"严格模式"或检查后端几何归一化算法`
          }
          
          // 🔥 即使失败也触发事件，得分为0
          logger.warn('⚠️ [JudgeComparisonPopup] 自动图片比对失败，触发 judge-complete 事件（得分0）')
          emit('judge-complete', {
            score: 0,
            similar: false,
            feedback: comparisonResult.value?.feedback || '比对失败'
          })
        }

      } catch (error) {
        logger.error('自动图片比对失败:', error)
        comparisonResult.value = {
          score: 0,
          feedback: `比对失败: ${error.message}`
        }
        
        // 🔥 异常时也触发事件，得分为0
        logger.error('❌ [JudgeComparisonPopup] 自动图片比对异常，触发 judge-complete 事件（得分0）')
        emit('judge-complete', {
          score: 0,
          similar: false,
          feedback: `比对失败: ${error.message}`
        })
      } finally {
        isComparing.value = false
      }
    }

    // 图片比对方法
    const compareImages = async () => {
      if (!canCompare.value) {
        logger.warn('无法进行图片比对：画布未准备好')
        return
      }

      try {
        isComparing.value = true
        comparisonResult.value = null
        logger.log('开始图片比对...')

        // 获取两张图片的Base64数据
        const standardBase64 = canvasToBase64(standardCanvas.value)
        const userBase64 = canvasToBase64(userCanvas.value)

        logger.log('标准图片Base64长度:', standardBase64 ? standardBase64.length : 0)
        logger.log('用户图片Base64长度:', userBase64 ? userBase64.length : 0)
        
        // 检查画布内容
        const standardCtx = standardCanvas.value.getContext('2d')
        const userCtx = userCanvas.value.getContext('2d')
        const standardImageData = standardCtx.getImageData(0, 0, standardCanvas.value.width, standardCanvas.value.height)
        const userImageData = userCtx.getImageData(0, 0, userCanvas.value.width, userCanvas.value.height)
        
        // 检查是否有非透明像素
        let standardHasContent = false
        let userHasContent = false
        
        for (let i = 3; i < standardImageData.data.length; i += 4) {
          if (standardImageData.data[i] > 0) { // alpha > 0
            standardHasContent = true
            break
          }
        }
        
        for (let i = 3; i < userImageData.data.length; i += 4) {
          if (userImageData.data[i] > 0) { // alpha > 0
            userHasContent = true
            break
          }
        }
        
        logger.log('画布内容检查:', {
          standardHasContent,
          userHasContent,
          standardCanvasSize: `${standardCanvas.value.width}x${standardCanvas.value.height}`,
          userCanvasSize: `${userCanvas.value.width}x${userCanvas.value.height}`
        })
        
        // 在控制台显示图片，方便调试
        console.log('=== 标准图片 Base64 ===')
        console.log(standardBase64)
        console.log('=== 用户图片 Base64 ===')
        console.log(userBase64)
        
        // 创建图片预览（可选）
        if (standardBase64) {
          const standardImg = new Image()
          standardImg.src = standardBase64
          standardImg.onload = () => {
            console.log('标准图片加载成功，尺寸:', standardImg.width, 'x', standardImg.height)
          }
        }
        
        if (userBase64) {
          const userImg = new Image()
          userImg.src = userBase64
          userImg.onload = () => {
            console.log('用户图片加载成功，尺寸:', userImg.width, 'x', userImg.height)
          }
        }

        if (!standardBase64 || !userBase64) {
          throw new Error('无法获取画布图片数据')
        }

        // 转换为Blob
        const standardBlob = base64ToBlob(standardBase64)
        const userBlob = base64ToBlob(userBase64)

        // 创建FormData
        const formData = new FormData()
        formData.append('image1', standardBlob, 'standard.png')
        formData.append('image2', userBlob, 'user.png')
        formData.append('strict', 'true')

        // 调用后端接口
        logger.log('准备发送请求到后端...')
        logger.log('请求URL:', '/api/goc/images/compare')
        logger.log('FormData内容:')
        for (let [key, value] of formData.entries()) {
          if (value instanceof File || value instanceof Blob) {
            logger.log(`  ${key}: [File/Blob, size: ${value.size} bytes, type: ${value.type}]`)
          } else {
            logger.log(`  ${key}: ${value}`)
          }
        }
        
        // 获取用户 token
        const token = localStorage.getItem('token')
        const headers = {}
        
        if (token) {
          headers['Authorization'] = token // 完整的 JWT 令牌，如截图中所示
          logger.log('🔑 已添加 Authorization 标头，token 长度:', token.length)
          logger.log('🔑 Authorization 标头内容:', token.substring(0, 50) + '...')
        } else {
          logger.warn('⚠️ 未找到用户 token，将不发送 Authorization 标头')
        }
        
        const response = await fetch('/api/goc/images/compare', {
          method: 'POST',
          headers: headers,
          body: formData
        })
        
        logger.log('后端响应状态:', response.status, response.statusText)
        logger.log('响应头:', Object.fromEntries(response.headers.entries()))

        if (!response.ok) {
          throw new Error(`HTTP错误: ${response.status}`)
        }

        const result = await response.json()
        logger.log('图片比对结果:', result)

        // 处理返回结果
        if (result.code === 0) {
          comparisonResult.value = {
            score: result.data?.score || 0,
            feedback: result.data?.feedback || result.message || '比对完成'
          }
        } else {
          // 更详细的错误信息
          const errorMsg = result.message || result.data || '比对失败'
          logger.error('后端返回错误:', { code: result.code, message: errorMsg, fullResult: result })
          
          // 特殊处理 Lorem Ipsum 错误（后端测试数据）
          if (errorMsg.includes('ipsum') || errorMsg.includes('lorem') || errorMsg.includes('cupidatat')) {
            comparisonResult.value = {
              score: 0,
              feedback: `后端服务异常 (错误码: ${result.code})，请联系后端开发者检查图片比对逻辑`
            }
          } else {
            // 如果是位置不匹配的错误，建议关闭严格模式
            if (errorMsg.includes('不相似') || errorMsg.includes('位置') || result.code === 1) {
              comparisonResult.value = {
                score: 0,
                feedback: `比对失败: ${errorMsg}。建议尝试关闭"严格模式"或检查后端几何归一化算法`
              }
            } else {
              throw new Error(`后端错误 (${result.code}): ${errorMsg}`)
            }
          }
        }

      } catch (error) {
        logger.error('图片比对失败:', error)
        comparisonResult.value = {
          score: 0,
          feedback: `比对失败: ${error.message}`
        }
      } finally {
        isComparing.value = false
      }
    }

    // 执行单个测试用例的图片比对
    const compareSingleTestCase = async (testCaseIndex) => {
      logger.log(`开始执行测试用例 ${testCaseIndex + 1}...`)
      
      try {
        // 执行标准代码和用户代码
        await Promise.all([
          executeStandardCode(testCaseIndex),
          executeUserCode(testCaseIndex)
        ])
        
        // 等待画布渲染完成
        await new Promise(resolve => setTimeout(resolve, 500))
        
        // 获取图片数据
        const standardBase64 = canvasToBase64(standardCanvas.value)
        const userBase64 = canvasToBase64(userCanvas.value)
        
        if (!standardBase64 || !userBase64) {
          throw new Error('无法获取图片数据')
        }
        
        // 转换为Blob
        const standardBlob = base64ToBlob(standardBase64)
        const userBlob = base64ToBlob(userBase64)
        
        // 创建FormData
        const formData = new FormData()
        formData.append('image1', standardBlob, 'standard.png')
        formData.append('image2', userBlob, 'user.png')
        formData.append('strict', 'true')
        
        // 发送请求
        const token = localStorage.getItem('token')
        const headers = {}
        if (token) {
          headers['Authorization'] = token
        }
        
        const response = await fetch('/api/goc/images/compare', {
          method: 'POST',
          headers: headers,
          body: formData
        })
        
        if (!response.ok) {
          throw new Error(`HTTP错误: ${response.status}`)
        }
        
        const result = await response.json()
        logger.log(`测试用例 ${testCaseIndex + 1} 比对结果:`, result)
        
        // 返回结果
        return {
          testCaseIndex,
          success: result.code === 0,
          score: result.data?.score || 0,
          feedback: result.data?.feedback || result.message || '比对完成',
          error: result.code !== 0 ? result.message : null
        }
        
      } catch (error) {
        logger.error(`测试用例 ${testCaseIndex + 1} 执行失败:`, error)
        return {
          testCaseIndex,
          success: false,
          score: 0,
          feedback: `执行失败: ${error.message}`,
          error: error.message
        }
      }
    }

    // 执行所有测试用例的图片比对
    const compareAllTestCases = async () => {
      if (!hasInputType.value) {
        logger.warn('当前不是有输入型题目，无法执行多测试用例比对')
        return
      }
      
      if (safeTestCasesLength.value === 0) {
        logger.warn('没有测试用例数据')
        return
      }
      
      try {
        isRunningAllTests.value = true
        testCaseResults.value = []
        overallScore.value = 0
        
        const testCasesLength = safeTestCasesLength.value
        logger.log(`开始执行 ${testCasesLength} 个测试用例...`)
        
        // 逐个执行测试用例
        for (let i = 0; i < testCasesLength; i++) {
          logger.log(`执行测试用例 ${i + 1}/${testCasesLength}`)
          
          const result = await compareSingleTestCase(i)
          testCaseResults.value.push(result)
          
          // 更新当前测试用例索引
          currentTestCaseIndex.value = i
          
          // 短暂延迟，让用户看到进度
          await new Promise(resolve => setTimeout(resolve, 1000))
        }
        
        // 计算总体分数
        const successfulTests = testCaseResults.value.filter(r => r.success)
        if (successfulTests.length > 0) {
          overallScore.value = Math.round(
            successfulTests.reduce((sum, r) => sum + r.score, 0) / successfulTests.length
          )
        }
        
        logger.log('所有测试用例执行完成:', {
          total: testCasesLength,
          successful: successfulTests.length,
          overallScore: overallScore.value,
          results: testCaseResults.value
        })
        
        // 显示最终结果
        comparisonResult.value = {
          score: overallScore.value,
          feedback: `完成 ${testCasesLength} 个测试用例，成功 ${successfulTests.length} 个，平均分数: ${overallScore.value}`,
          testCaseResults: testCaseResults.value
        }
        
        // 🔥 触发判题完成事件，传递得分给父组件
        logger.log('🚨🚨🚨 [JudgeComparisonPopup] ========== compareAllTestCases 触发 judge-complete 事件！ ==========')
        logger.log('✅ [JudgeComparisonPopup] 所有测试用例执行完成，触发 judge-complete 事件')
        logger.log('📊 [JudgeComparisonPopup] 平均得分:', overallScore.value)
        logger.log('📊 [JudgeComparisonPopup] 成功测试用例:', successfulTests.length)
        
        const judgeCompleteData = {
          score: overallScore.value,
          similar: overallScore.value > 0, // 有得分就认为相似
          feedback: `完成 ${testCasesLength} 个测试用例，成功 ${successfulTests.length} 个，平均分数: ${overallScore.value}`,
          testCaseResults: testCaseResults.value
        }
        logger.log('📤 [JudgeComparisonPopup] 发送的数据:', judgeCompleteData)
        
        emit('judge-complete', judgeCompleteData)
        
        logger.log('✅ [JudgeComparisonPopup] judge-complete 事件已触发')
        
      } catch (error) {
        logger.error('执行所有测试用例失败:', error)
        comparisonResult.value = {
          score: 0,
          feedback: `执行失败: ${error.message}`,
          testCaseResults: testCaseResults.value
        }
      } finally {
        isRunningAllTests.value = false
      }
    }

    // 下载图片到本地
    const downloadImages = () => {
      if (!standardCanvas.value || !userCanvas.value) {
        logger.warn('画布未准备好，无法下载图片')
        return
      }

      // 获取Base64数据
      const standardBase64 = canvasToBase64(standardCanvas.value)
      const userBase64 = canvasToBase64(userCanvas.value)

      if (!standardBase64 || !userBase64) {
        logger.warn('无法获取图片数据')
        return
      }

      // 创建下载链接
      const downloadImage = (base64Data, filename) => {
        const link = document.createElement('a')
        link.href = base64Data
        link.download = filename
        document.body.appendChild(link)
        link.click()
        document.body.removeChild(link)
      }

      // 下载标准答案图片
      downloadImage(standardBase64, 'standard_answer.png')
      
      // 延迟下载用户答案图片，避免浏览器阻止多个下载
      setTimeout(() => {
        downloadImage(userBase64, 'user_answer.png')
      }, 500)

      logger.log('图片下载已开始')
    }

    // 执行标准代码（支持指定测试用例）
    const executeStandardCode = async (testCaseIndex = 0) => {
      if (!props.answerCode || !standardCanvas.value) {
        logger.warn('无法执行标准代码:', { answerCode: props.answerCode, canvas: standardCanvas.value })
        return
      }

      // 调试信息：检查props
      logger.log('🔍 executeStandardCode 调试信息:', {
        testCaseIndex,
        testCasesLength: safeTestCasesLength.value,
        testCases: safeTestCases.value,
        answerCode: props.answerCode
      })

      try {
        isExecuting.value = true
        logger.log(`开始执行标准代码 (测试用例 ${testCaseIndex + 1})...`, props.answerCode)

        // 清除画布
        const ctx = standardCanvas.value.getContext('2d')
        ctx.clearRect(0, 0, standardCanvas.value.width, standardCanvas.value.height)

        // 初始化GOC解释器需要的全局变量
        window.__gocUpdatePen = () => {} // 空函数，不需要画笔动画
        window.__gocSetPenVisible = () => {} // 空函数，不需要画笔可见性控制
        window.__gocSpeedLevel = 10 // 设置速度为10，用于判题弹窗中的图形绘制

        // 🔥 获取指定测试数据的输入（现在使用测试数据而不是测试用例）
        const testCase = safeTestCases.value[testCaseIndex] || null
        if (testCase && testCase.input) {
          standardInput.value = testCase.input
          logger.log(`📥 使用测试数据 ${testCaseIndex + 1} 输入:`, testCase.input)
        } else {
          standardInput.value = ''
          logger.log('📥 无测试数据输入')
        }

        // 动态导入执行器
        const { tokenize } = await import('../utils/goc-tokenizer.js')
        const { parse } = await import('../utils/goc-parser.js')
        const { execute } = await import('../utils/goc-interpreter.js')

        // 分词 -> 解析 -> 执行
        logger.log('开始分词...')
        const tokens = tokenize(props.answerCode)
        logger.log('分词结果:', tokens)
        
        logger.log('开始解析...')
        const ast = parse(tokens)
        logger.log('解析结果:', ast)
        
        logger.log('开始执行代码...')
        // 执行代码，提供ioMethods来处理cin输入
        let inputIndex = 0 // 当前输入索引
        let inputValues = [] // 解析后的输入值数组
        
        const ioMethods = {
          waitForInput: () => {
            // 🔥 从测试数据中获取输入数据（现在使用测试数据而不是测试用例）
            logger.log(`🔍 标准代码调试信息: testCaseIndex=${testCaseIndex}, testCases.length=${safeTestCasesLength.value}`)
            logger.log(`🔍 测试数据:`, safeTestCases.value)
            
            const testCase = safeTestCases.value[testCaseIndex] || null
            if (testCase && testCase.input) {
              // 如果是第一次调用，解析输入字符串
              if (inputIndex === 0) {
                inputValues = testCase.input.trim().split(/\s+/).filter(val => val.length > 0)
                logger.log(`📥 解析测试数据输入字符串: "${testCase.input}" -> [${inputValues.join(', ')}]`)
              }
              
              // 返回当前索引的值
              if (inputIndex < inputValues.length) {
                const value = inputValues[inputIndex]
                logger.log(`📥 返回第${inputIndex + 1}个输入值: ${value}`)
                inputIndex++
                return value
              } else {
                logger.warn(`⚠️ 输入索引超出范围: ${inputIndex} >= ${inputValues.length}`)
                return '0' // 默认值
              }
            }
            logger.warn('⚠️ 没有找到测试数据输入')
            return '0' // 默认值
          },
          setInputMode: (mode) => {
            logger.log(`📥 设置输入模式: ${mode}`)
          }
        }
        await execute(ast, ctx, null, ioMethods)
        logger.log('代码执行完成')
        
        // 检查画布是否有内容
        const imageData = ctx.getImageData(0, 0, standardCanvas.value.width, standardCanvas.value.height)
        const hasContent = imageData.data.some((value, index) => index % 4 !== 3 && value !== 0) // 检查非透明像素
        logger.log('画布是否有内容:', hasContent)

        standardOutput.value = `标准代码执行完成`

        logger.log('标准代码执行完成，画布尺寸:', standardCanvas.value.width, 'x', standardCanvas.value.height)

      } catch (error) {
        logger.error('执行标准代码失败:', error)
        standardOutput.value = `执行失败: ${error.message}`
      } finally {
        isExecuting.value = false
      }
    }

    // 执行用户代码（支持指定测试用例）
    const executeUserCode = async (testCaseIndex = 0) => {
      if (!props.userCode || !userCanvas.value) {
        logger.warn('无法执行用户代码:', { userCode: props.userCode, canvas: userCanvas.value })
        return
      }

      // 调试信息：检查props
      logger.log('🔍 executeUserCode 调试信息:', {
        testCaseIndex,
        testCasesLength: safeTestCasesLength.value,
        testCases: safeTestCases.value,
        userCode: props.userCode
      })

      try {
        isExecuting.value = true
        logger.log(`开始执行用户代码 (测试用例 ${testCaseIndex + 1})...`, props.userCode)

        // 清除画布
        const ctx = userCanvas.value.getContext('2d')
        ctx.clearRect(0, 0, userCanvas.value.width, userCanvas.value.height)

        // 初始化GOC解释器需要的全局变量
        window.__gocUpdatePen = () => {} // 空函数，不需要画笔动画
        window.__gocSetPenVisible = () => {} // 空函数，不需要画笔可见性控制
        window.__gocSpeedLevel = 10 // 设置速度为10，用于判题弹窗中的图形绘制

        // 🔥 获取指定测试数据的输入（现在使用测试数据而不是测试用例）
        const testCase = safeTestCases.value[testCaseIndex] || null
        if (testCase && testCase.input) {
          userInput.value = testCase.input
          logger.log(`📥 使用测试数据 ${testCaseIndex + 1} 输入:`, testCase.input)
        } else {
          userInput.value = ''
          logger.log('📥 无测试数据输入')
        }

        // 动态导入执行器
        const { tokenize } = await import('../utils/goc-tokenizer.js')
        const { parse } = await import('../utils/goc-parser.js')
        const { execute } = await import('../utils/goc-interpreter.js')

        // 分词 -> 解析 -> 执行
        logger.log('开始分词用户代码...')
        const tokens = tokenize(props.userCode)
        logger.log('用户代码分词结果:', tokens)
        
        logger.log('开始解析用户代码...')
        const ast = parse(tokens)
        logger.log('用户代码解析结果:', ast)
        
        logger.log('开始执行用户代码...')
        // 执行代码，提供ioMethods来处理cin输入
        let userInputIndex = 0 // 当前输入索引
        let userInputValues = [] // 解析后的输入值数组
        
        const ioMethods = {
          waitForInput: () => {
            // 🔥 从测试数据中获取输入数据（现在使用测试数据而不是测试用例）
            logger.log(`🔍 用户代码调试信息: testCaseIndex=${testCaseIndex}, testCases.length=${safeTestCasesLength.value}`)
            logger.log(`🔍 测试数据:`, safeTestCases.value)
            
            const testCase = safeTestCases.value[testCaseIndex] || null
            if (testCase && testCase.input) {
              // 如果是第一次调用，解析输入字符串
              if (userInputIndex === 0) {
                userInputValues = testCase.input.trim().split(/\s+/).filter(val => val.length > 0)
                logger.log(`📥 解析测试数据输入字符串: "${testCase.input}" -> [${userInputValues.join(', ')}]`)
              }
              
              // 返回当前索引的值
              if (userInputIndex < userInputValues.length) {
                const value = userInputValues[userInputIndex]
                logger.log(`📥 返回用户第${userInputIndex + 1}个输入值: ${value}`)
                userInputIndex++
                return value
              } else {
                logger.warn(`⚠️ 用户输入索引超出范围: ${userInputIndex} >= ${userInputValues.length}`)
                return '0' // 默认值
              }
            }
            logger.warn('⚠️ 没有找到测试数据输入')
            return '0' // 默认值
          },
          setInputMode: (mode) => {
            logger.log(`📥 设置输入模式: ${mode}`)
          }
        }
        await execute(ast, ctx, null, ioMethods)
        logger.log('用户代码执行完成')
        
        // 检查画布是否有内容
        const imageData = ctx.getImageData(0, 0, userCanvas.value.width, userCanvas.value.height)
        const hasContent = imageData.data.some((value, index) => index % 4 !== 3 && value !== 0) // 检查非透明像素
        logger.log('用户画布是否有内容:', hasContent)

        userOutput.value = `用户代码执行完成`

        logger.log('用户代码执行完成，画布尺寸:', userCanvas.value.width, 'x', userCanvas.value.height)

      } catch (error) {
        logger.error('执行用户代码失败:', error)
        userOutput.value = `执行失败: ${error.message}`
      } finally {
        isExecuting.value = false
      }
    }

    // 监听弹窗显示状态，当显示时执行代码并自动进行图片对比
    watch(() => props.visible, async (newVisible) => {
      if (newVisible) {
        await nextTick()
        
        // 根据状态变量设置坐标轴画布的显示状态
        if (standardAxisCanvas.value) {
          standardAxisCanvas.value.style.display = showStandardCoordinates.value ? 'block' : 'none'
          if (showStandardCoordinates.value) {
            drawCoordinateGrid(standardAxisCanvas.value, 900, 900)
          }
        }
        if (userAxisCanvas.value) {
          userAxisCanvas.value.style.display = showUserCoordinates.value ? 'block' : 'none'
          if (showUserCoordinates.value) {
            drawCoordinateGrid(userAxisCanvas.value, 900, 900)
          }
        }
        
        // 并行执行标准代码和用户代码
        await Promise.all([
          executeStandardCode(),
          executeUserCode()
        ])
        
        // 自动执行图片对比
        logger.log('🚀 弹窗显示完成，开始自动图片对比...')
        await autoCompareImages()
      }
    })

    // 监听代码变化，重新执行
    watch(() => [props.userCode, props.answerCode], async () => {
      if (props.visible) {
        await nextTick()
        await Promise.all([
          executeStandardCode(),
          executeUserCode()
        ])
      }
    })

    return {
      standardCanvas,
      userCanvas,
      standardAxisCanvas,
      userAxisCanvas,
      standardInput,
      standardOutput,
      userInput,
      userOutput,
      isExecuting,
      isComparing,
      comparisonResult,
      canCompare,
      showStandardCoordinates,
      showUserCoordinates,
      // 有输入型题目相关
      currentTestCaseIndex,
      testCaseResults,
      isRunningAllTests,
      overallScore,
      hasInputType,
      safeTestCases,
      safeTestCasesLength,
      getTestCaseInput,
      closePopup,
      handleOverlayClick,
      drawCoordinates,
      compareImages,
      autoCompareImages,
      compareSingleTestCase,
      compareAllTestCases,
      downloadImages
    }
  }
}
</script>

<style scoped>
.judge-popup-overlay {
  position: fixed;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  background: rgba(0, 0, 0, 0.5);
  display: flex;
  justify-content: center;
  align-items: center;
  z-index: 1000;
}

.judge-popup {
  background: white;
  border-radius: 8px;
  box-shadow: 0 4px 20px rgba(0, 0, 0, 0.3);
  width: 95%;
  max-width: 1800px;
  max-height: 95%;
  overflow: hidden;
  display: flex;
  flex-direction: column;
}

.popup-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 20px;
  border-bottom: 1px solid #e0e0e0;
  background: #f8f9fa;
}

.popup-title {
  margin: 0;
  font-size: 18px;
  font-weight: bold;
  color: #333;
}

.close-btn {
  background: none;
  border: none;
  font-size: 24px;
  cursor: pointer;
  color: #666;
  padding: 0;
  width: 30px;
  height: 30px;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: 50%;
  transition: background-color 0.2s;
}

.close-btn:hover {
  background: #e0e0e0;
}

.popup-content {
  display: flex;
  flex: 1;
  min-height: 0;
}

.left-section,
.middle-section {
  flex: 1;
  padding: 20px;
  border-right: 1px solid #e0e0e0;
  display: flex;
  flex-direction: column;
  min-width: 0;
}

.right-section {
  flex: 0 0 300px;
  background: #4caf50;
  color: white;
  padding: 20px;
  display: flex;
  flex-direction: column;
}

.section-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 15px;
}

.section-title {
  margin: 0;
  font-size: 16px;
  font-weight: bold;
  color: #333;
}

.draw-coords-btn {
  background: #4caf50;
  color: white;
  border: none;
  padding: 6px 12px;
  border-radius: 4px;
  cursor: pointer;
  font-size: 12px;
  display: flex;
  align-items: center;
  gap: 4px;
  transition: background-color 0.2s;
}

.draw-coords-btn:hover {
  background: #45a049;
}

.btn-icon {
  font-size: 10px;
}

.canvas-container {
  flex: 1;
  display: flex;
  justify-content: flex-start;
  align-items: flex-start;
  background: #f8f9fa;
  border: 1px solid #e0e0e0;
  border-radius: 4px;
  margin-bottom: 15px;
  min-height: 500px;
  overflow: auto;
  overflow-x: auto;
  overflow-y: auto;
  padding: 10px;
}

.canvas-wrap {
  position: relative;
  width: 900px;
  height: 900px;
  border-radius: 4px;
  overflow: hidden;
  background: #fff;
  flex-shrink: 0;
}

.canvas-wrap canvas {
  position: absolute;
  left: 0;
  top: 0;
  border: none;
  border-radius: 4px;
}

.axis-canvas {
  z-index: 1; /* 坐标轴画布 - 上层 */
  background: transparent; /* 透明背景，不覆盖下层内容 */
}

.judge-canvas {
  z-index: 0; /* 绘制画布 - 底层 */
  background: white;
}


.io-fields {
  display: flex;
  gap: 10px;
}

.io-field {
  flex: 1;
  display: flex;
  flex-direction: column;
  gap: 4px;
}

.io-field label {
  font-size: 12px;
  font-weight: bold;
  color: #666;
}

.io-field input {
  padding: 6px 8px;
  border: 1px solid #ddd;
  border-radius: 4px;
  font-size: 12px;
  background: #f8f9fa;

}

.test-complete-header {
  text-align: center;
  margin-bottom: 20px;
}

.test-complete-title {
  margin: 0;
  font-size: 18px;
  font-weight: bold;
}

/* 比对控制区域样式 */
.comparison-controls {
  margin-bottom: 20px;
  padding: 15px;
  background: rgba(255, 255, 255, 0.1);
  border-radius: 6px;
}

/* 自动图片对比提示样式 */
.auto-compare-notice {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 12px;
  background: rgba(255, 255, 255, 0.2);
  border-radius: 6px;
  margin-bottom: 10px;
  border: 2px solid #ff9800;
}

.notice-icon {
  font-size: 18px;
  animation: spin 1s linear infinite;
}

.notice-text {
  font-size: 14px;
  font-weight: 500;
  color: white;
}

@keyframes spin {
  from { transform: rotate(0deg); }
  to { transform: rotate(360deg); }
}

.compare-btn {
  width: 100%;
  padding: 12px;
  background: #ff9800;
  color: white;
  border: none;
  border-radius: 4px;
  cursor: pointer;
  font-size: 14px;
  font-weight: bold;
  margin-bottom: 10px;
  transition: background-color 0.2s;
}

.compare-btn:hover:not(:disabled) {
  background: #f57c00;
}

.compare-btn:disabled {
  background: #ccc;
  cursor: not-allowed;
}

.download-btn {
  width: 100%;
  padding: 8px;
  background: #4caf50;
  color: white;
  border: none;
  border-radius: 4px;
  cursor: pointer;
  font-size: 12px;
  font-weight: bold;
  margin-bottom: 10px;
  transition: background-color 0.2s;
}

.download-btn:hover {
  background: #45a049;
}

/* 比对结果样式 */
.comparison-result {
  margin-bottom: 20px;
  padding: 15px;
  background: #ffffff;
  border-radius: 6px;
  color: #333;
  border: 1px solid #e0e0e0;
}

.comparison-result h5 {
  margin: 0 0 10px 0;
  font-size: 14px;
  font-weight: bold;
}

.result-score {
  font-size: 16px;
  font-weight: bold;
  margin-bottom: 8px;
  color: #04fc4e;
}

.result-details {
  font-size: 12px;
  line-height: 1.4;
  color: #495057;
}

.results-table {
  flex: 1;
  overflow-y: auto;
}

.results-table table {
  width: 100%;
  border-collapse: collapse;
  background: white;
  border-radius: 4px;
  overflow: hidden;
}

.results-table th,
.results-table td {
  padding: 8px 12px;
  text-align: left;
  border-bottom: 1px solid #e0e0e0;
}

.results-table th {
  background: #f8f9fa;
  font-weight: bold;
  color: #333;
  font-size: 12px;
}

.results-table td {
  font-size: 12px;
  color: #666;
}

.results-table tr:last-child td {
  border-bottom: none;
}

/* 响应式设计 */
@media (max-width: 1200px) {
  .judge-popup {
    width: 98%;
    max-width: 1600px;
  }
  
  .canvas-container {
    min-height: 400px;
  }
  
  .judge-canvas {
    max-width: 90%;
    max-height: 90%;
  }
}

@media (max-width: 768px) {
  .judge-popup {
    width: 95%;
    height: 95%;
  }
  
  .popup-content {
    flex-direction: column;
  }
  
  .left-section,
  .middle-section {
    border-right: none;
    border-bottom: 1px solid #e0e0e0;
  }
  
  .right-section {
    flex: none;
  }
  
  .canvas-container {
    min-height: 300px;
  }
  
  .judge-canvas {
    max-width: 100%;
    max-height: 100%;
  }
}

/* 有输入型题目相关样式 */
.input-type-controls {
  margin-top: 15px;
  padding: 10px;
  background: #f8f9fa;
  border-radius: 6px;
  border: 1px solid #e9ecef;
}

.run-all-tests-btn {
  background: linear-gradient(135deg, #28a745, #20c997);
  color: white;
  border: none;
  padding: 10px 20px;
  border-radius: 6px;
  cursor: pointer;
  font-size: 14px;
  font-weight: 500;
  transition: all 0.3s ease;
  margin-bottom: 10px;
  width: 100%;
}

.run-all-tests-btn:hover:not(:disabled) {
  background: linear-gradient(135deg, #218838, #1ea085);
  transform: translateY(-1px);
  box-shadow: 0 4px 12px rgba(40, 167, 69, 0.3);
}

.run-all-tests-btn:disabled {
  background: #6c757d;
  cursor: not-allowed;
  transform: none;
  box-shadow: none;
}

.test-progress {
  text-align: center;
  font-size: 12px;
  color: #6c757d;
  font-weight: 500;
}

.test-case-results {
  margin-top: 20px;
  padding: 15px;
  background: #f8f9fa;
  border-radius: 8px;
  border: 1px solid #e9ecef;
}

.test-case-results h6 {
  margin: 0 0 15px 0;
  color: #495057;
  font-size: 14px;
  font-weight: 600;
}

.test-case-list {
  display: flex;
  flex-direction: column;
  gap: 10px;
}

.test-case-item {
  padding: 12px;
  border-radius: 6px;
  border: 1px solid #dee2e6;
  background: white;
  transition: all 0.2s ease;
}

.test-case-item.success {
  border-color: #28a745;
  background: #f8fff9;
}

.test-case-item.error {
  border-color: #dc3545;
  background: #fff8f8;
}

.test-case-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 8px;
}

.test-case-number {
  font-weight: 600;
  color: #495057;
  font-size: 13px;
}

.test-case-score {
  font-weight: 600;
  color: #28a745;
  font-size: 13px;
}

.test-case-item.error .test-case-score {
  color: #dc3545;
}

.test-case-status {
  font-size: 16px;
  font-weight: bold;
}

.test-case-item.success .test-case-status {
  color: #28a745;
}

.test-case-item.error .test-case-status {
  color: #dc3545;
}

.test-case-input {
  margin-bottom: 6px;
  font-size: 12px;
  color: #6c757d;
}

.test-case-input strong {
  color: #495057;
}

.test-case-feedback {
  font-size: 12px;
  color: #495057;
  margin-bottom: 4px;
}

.test-case-error {
  font-size: 11px;
  color: #dc3545;
  font-style: italic;
}
</style>

